
/**
 * 一、将异步代码使用Promise方法改进
 */
//原代码
setTimeout(function () {
    var a= 'hello'
    setTimeout(function () {
        var b= 'lagou'
        setTimeout(function () {
            var c= 'I ♥ U'
            console.log(a + b +c)
        }, 10);
    }, 10)
}, 10)

/****************** 答题 **************/
function f(str){
    return new Promise((resolve, reject)=>{
        setTimeout(value => {
            resolve(str);
        }, 10)
    })
}
f('hello').then(value => value + 'lagou').then(value => value + 'I ♥ U').then(value => console.log(value))




/**
 * 二、基于以下代码完成下面的四个练习
 */
const fp = require('lodash/fp');
// 数据: horsepower 马力， dollar_value 价格, on_stock 库存
const cars=[
    { name: 'Ferrari FF', horsepower: 660, dollar_value: 700000, in_stock: true},
    { name: 'Spyker C12 Zagato', horsepower: 650, dollar_value: 648000, in_stock: false},
    { name: 'Jaguar XKR-s', horsepower: 550, dollar_value: 132000, in_stock: false},
    { name: 'Audi R8', horsepower: 525, dollar_value: 124100, in_stock: false},
    { name: 'Aston Martin One-77', horsepower: 750, dollar_value: 185000, in_stock: true},
    { name: 'Pagani Huayra', horsepower: 700, dollar_value: 130000, in_stock: true},
]


/**
 * 二、练习1: 使用函数组合fp.flowRight() 重新实现下面这个函数
 */
let isLastInStock = function (cars) {
    //获取最后一条数据
    let last_car = fp.last(cars)
    //获取最后一条数据的 in_stock 属性值
    return fp.prop('in_stock', last_car)
}
console.log(isLastInStock(cars));

/****************** 答题 **************/
let isLastInStock_1 = fp.flowRight(fp.prop('in_stock'), fp.last);
console.log(isLastInStock_1(cars));


/**
 * 二、练习2: 使用fp.flowRight()、fp.prop() 和fp.first()获取第一个car的name
 */

/****************** 答题 **************/
let firstCarName = fp.flowRight(fp.prop('name'), fp.first);
console.log(firstCarName(cars));

/**
 * 二、练习3: 使用帮助函数_average重构averageDollarValue, 使用函数组合的方式实现
 */
let _average = function (xs) {
    return fp.reduce(fp.add, 0, xs) / xs.length
} //<- 无须改动
let averageDollarValue = function (cars) {
    let dollar_values = fp.map(function (car) {
        return car.dollar_value
    }, cars)
    return _average(dollar_values)
}
console.log(averageDollarValue(cars));

/****************** 答题 **************/
let averageDollarValue_1 = fp.flowRight(_average, fp.map(car => car.dollar_value));
console.log(averageDollarValue_1(cars));


/**
 * 二、练习4: 使用flowRight写一个sanitizeNames()函数，返回一个下划线连接的小写字符串，
 * 把数组中的name转换成为这种形式： 例如：sanitizeNames(["Hello World"]) => ["hello_world"]
 */
let _underscore = fp.replace(/\W+/g, '_') // <-- 无须改动，并再sanitizeNames中使用它

/****************** 答题 **************/
let sanitizeNames = fp.map(fp.flowRight(fp.toLower, _underscore));
console.log(sanitizeNames(["Hello World"]));



/**
 * 三、基于下面提供的代码，完成后续的四个练习
 */

class Container {
    static of(value) {
        return new Container (value)
    }
    constructor(value) {
        this._value = value
    }
    map(fn) {
        return Container.of(fn(this._value))
    }
}

class Maybe {
    static of(x) {
        return new Maybe(x)
    }
    isNothing() {
        return this._value === null || this._value === undefined
    }
    constructor(x) {
        this._value = x
    }
    map(fn) {
        return this.isNothing() ? this : Maybe.of(fn(this._value))
    }
}


/**
 * 三、练习1：使用fp.add(x,y)和fp.map(f,x)创建一个能让functor里的值增加的函数 ex1 
 */

let maybe = Maybe.of([5, 6, 1])

/****************** 答题 **************/
let ex1 = value => {
    return fp.map(fp.curry(fp.add)(value))
};
console.log(maybe.map(ex1(1))._value);  //比如：每个数据 + 1


/**
 * 三、练习2：实现一个函数 ex2, 能够使用fp.first 获取列表的第一个元素
 */

let xs = Container.of(['do', 'ray', 'me', 'fa', 'so', 'la', 'ti', 'do'])

/****************** 答题 **************/
let ex2 = value => {
    // 你需要实现的函数。。。
    return value.map(fp.first)
};
console.log(ex2(xs)._value)


/**
 * 三、练习3： 实现一个函数ex3, 使用safeProp 和 fp.first 找到user的名字的首字母
 */

let safeProp = fp.curry(function (x, o){
    return Maybe.of(o[x])
})
let user = { id: 2, name: 'Albert' }

/****************** 答题 **************/
let ex3 = value => {
    // 你需要实现的函数。。。
    return fp.flowRight(fp.first, a => a._value, safeProp(value));
}
console.log(ex3('name')(user));



/**
 * 三、练习4：使用Maybe重写ex4, 不要有if语句
 */
let ex4 = function(n) {
    if(n){
        return parseInt(n)
    }
}

/****************** 答题 **************/
let ex4_1 = function(n) {
    let maybe = Maybe.of(n);
    return maybe.map(parseInt)._value;
}
console.log(ex4_1("23"));

/**
 * 手写实现 MyPromist 源码
 * 要求：尽可能还原Promist 中的每一个API, 并通过注释的方式描述思路和原理
 */

 /****************** 答题 **************/
 // 请参看当前目录下 MyPromiste.js 文件，整体思路请跟随注释里面的步骤标记 1, 2, 3, 4。。。走



